package com.cencat.user.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cencat.user.entity.RolePermission;
import com.cencat.user.dto.RolePermissionQueryDTO;
import com.cencat.user.vo.RolePermissionVO;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * 角色权限关联数据访问层
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Mapper
public interface RolePermissionMapper extends BaseMapper<RolePermission> {

    /**
     * 根据角色ID查询权限ID列表
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 权限ID列表
     */
    @Select("SELECT permission_id FROM sys_role_permission WHERE role_id = #{roleId} AND tenant_id = #{tenantId} AND deleted = 0")
    List<Long> selectPermissionIdsByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Long tenantId);

    /**
     * 根据权限ID查询角色ID列表
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 角色ID列表
     */
    @Select("SELECT role_id FROM sys_role_permission WHERE permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    List<Long> selectRoleIdsByPermissionId(@Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 检查角色权限关联是否存在
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 是否存在
     */
    @Select("SELECT COUNT(*) > 0 FROM sys_role_permission WHERE role_id = #{roleId} AND permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    boolean existsRolePermission(@Param("roleId") Long roleId, @Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 批量插入角色权限关联
     * @param rolePermissions 角色权限关联列表
     * @return 插入数量
     */
    int batchInsertRolePermissions(@Param("rolePermissions") List<RolePermission> rolePermissions);

    /**
     * 批量插入角色权限关联（简化方法名）
     * @param rolePermissions 角色权限关联列表
     * @return 插入数量
     */
    int batchInsert(@Param("rolePermissions") List<RolePermission> rolePermissions);

    /**
     * 根据角色ID和权限ID查询关联记录
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 角色权限关联记录
     */
    @Select("SELECT * FROM sys_role_permission WHERE role_id = #{roleId} AND permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    RolePermission selectByRoleIdAndPermissionId(@Param("roleId") Long roleId, @Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID删除权限关联
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 删除数量
     */
    @Update("UPDATE sys_role_permission SET deleted = 1, update_time = NOW() WHERE role_id = #{roleId} AND tenant_id = #{tenantId} AND deleted = 0")
    int deleteByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Long tenantId);

    /**
     * 根据权限ID删除角色关联
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 删除数量
     */
    @Update("UPDATE sys_role_permission SET deleted = 1, update_time = NOW() WHERE permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    int deleteByPermissionId(@Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID和权限ID列表删除关联
     * @param roleId 角色ID
     * @param permissionIds 权限ID列表
     * @return 删除数量
     */
    int batchDeleteRolePermissions(@Param("roleId") Long roleId, @Param("permissionIds") List<Long> permissionIds);

    /**
     * 分页查询角色权限关联
     * @param page 分页参数
     * @param queryDTO 查询条件
     * @return 分页结果
     */
    IPage<RolePermissionVO> selectRolePermissionPage(IPage<RolePermissionVO> page, @Param("query") RolePermissionQueryDTO queryDTO);

    /**
     * 查询角色权限关联列表
     * @param queryDTO 查询条件
     * @return 角色权限关联列表
     */
    List<RolePermissionVO> selectRolePermissionList(@Param("query") RolePermissionQueryDTO queryDTO);

    /**
     * 检查角色是否拥有权限
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 是否拥有权限
     */
    @Select("SELECT COUNT(*) > 0 FROM sys_role_permission WHERE role_id = #{roleId} AND permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    boolean hasPermission(@Param("roleId") Long roleId, @Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 根据用户ID查询角色权限关联
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 角色权限关联列表
     */
    @Select("SELECT rp.* FROM sys_role_permission rp " +
            "INNER JOIN sys_user_role ur ON rp.role_id = ur.role_id " +
            "WHERE ur.user_id = #{userId} AND ur.tenant_id = #{tenantId} " +
            "AND rp.deleted = 0 AND ur.deleted = 0")
    List<RolePermission> selectByUserId(@Param("userId") Long userId, @Param("tenantId") Long tenantId);

    /**
     * 统计角色权限关联数量
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 关联数量
     */
    @Select("SELECT COUNT(*) FROM sys_role_permission WHERE role_id = #{roleId} AND tenant_id = #{tenantId} AND deleted = 0")
    Long countByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Long tenantId);

    /**
     * 统计权限角色关联数量
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 关联数量
     */
    @Select("SELECT COUNT(*) FROM sys_role_permission WHERE permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    Long countByPermissionId(@Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 根据租户ID查询所有角色权限关联
     * @param tenantId 租户ID
     * @return 角色权限关联列表
     */
    @Select("SELECT * FROM sys_role_permission WHERE tenant_id = #{tenantId} AND deleted = 0 ORDER BY create_time DESC")
    List<RolePermission> selectByTenantId(@Param("tenantId") Long tenantId);
    
    /**
     * 根据角色ID查询角色权限关联列表
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 角色权限关联列表
     */
    @Select("SELECT * FROM sys_role_permission WHERE role_id = #{roleId} AND tenant_id = #{tenantId} AND deleted = 0 ORDER BY create_time DESC")
    List<RolePermission> selectByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID查询角色权限关联信息
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 角色权限关联信息
     */
    @Select("SELECT rp.*, p.permission_name, p.permission_code FROM sys_role_permission rp " +
            "LEFT JOIN sys_permission p ON rp.permission_id = p.id " +
            "WHERE rp.role_id = #{roleId} AND rp.tenant_id = #{tenantId} AND rp.deleted = 0")
    List<RolePermissionVO> selectRolePermissionByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID查询权限信息
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 权限信息列表
     */
    @Select("SELECT p.* FROM sys_permission p " +
            "INNER JOIN sys_role_permission rp ON p.id = rp.permission_id " +
            "WHERE rp.role_id = #{roleId} AND rp.tenant_id = #{tenantId} " +
            "AND p.deleted = 0 AND rp.deleted = 0")
    List<com.cencat.user.entity.Permission> selectPermissionsByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Long tenantId);

    /**
     * 根据权限ID查询角色信息（包含角色详情）
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 角色权限VO列表
     */
    @Select("SELECT r.id as role_id, r.role_name, r.role_code, rp.id, rp.create_time, rp.update_time " +
            "FROM sys_role r " +
            "INNER JOIN sys_role_permission rp ON r.id = rp.role_id " +
            "WHERE rp.permission_id = #{permissionId} AND rp.tenant_id = #{tenantId} " +
            "AND r.deleted = 0 AND rp.deleted = 0")
    List<RolePermissionVO> selectRolesByPermissionId(@Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID和权限ID列表删除关联关系
     * @param roleId 角色ID
     * @param permissionIds 权限ID列表
     * @param tenantId 租户ID
     * @return 删除数量
     */
    @Update("<script>" +
            "UPDATE sys_role_permission SET deleted = 1, update_time = NOW() " +
            "WHERE role_id = #{roleId} AND tenant_id = #{tenantId} " +
            "AND permission_id IN " +
            "<foreach collection='permissionIds' item='permissionId' open='(' separator=',' close=')'>" +
            "#{permissionId}" +
            "</foreach>" +
            "AND deleted = 0" +
            "</script>")
    int deleteByRoleIdAndPermissionIds(@Param("roleId") Long roleId, @Param("permissionIds") List<Long> permissionIds, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID列表查询权限ID列表
     * @param roleIds 角色ID列表
     * @param tenantId 租户ID
     * @return 权限ID列表
     */
    @Select("<script>" +
            "SELECT DISTINCT permission_id FROM sys_role_permission " +
            "WHERE tenant_id = #{tenantId} AND deleted = 0 " +
            "AND role_id IN " +
            "<foreach collection='roleIds' item='roleId' open='(' separator=',' close=')'>" +
            "#{roleId}" +
            "</foreach>" +
            "</script>")
    List<Long> selectPermissionIdsByRoleIds(@Param("roleIds") List<Long> roleIds, @Param("tenantId") Long tenantId);

    /**
     * 根据权限ID列表查询角色ID列表
     * @param permissionIds 权限ID列表
     * @param tenantId 租户ID
     * @return 角色ID列表
     */
    @Select("<script>" +
            "SELECT DISTINCT role_id FROM sys_role_permission " +
            "WHERE tenant_id = #{tenantId} AND deleted = 0 " +
            "AND permission_id IN " +
            "<foreach collection='permissionIds' item='permissionId' open='(' separator=',' close=')'>" +
            "#{permissionId}" +
            "</foreach>" +
            "</script>")
    List<Long> selectRoleIdsByPermissionIds(@Param("permissionIds") List<Long> permissionIds, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID和权限ID删除关联
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 删除数量
     */
    @Update("UPDATE sys_role_permission SET deleted = 1, update_time = NOW() WHERE role_id = #{roleId} AND permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    int deleteByRoleIdAndPermissionId(@Param("roleId") Long roleId, @Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 根据角色ID列表删除权限关联
     * @param roleIds 角色ID列表
     * @param tenantId 租户ID
     * @return 删除数量
     */
    int deleteByRoleIds(@Param("roleIds") List<Long> roleIds, @Param("tenantId") Long tenantId);

    /**
     * 根据权限ID列表删除角色关联
     * @param permissionIds 权限ID列表
     * @param tenantId 租户ID
     * @return 删除数量
     */
    int deleteByPermissionIds(@Param("permissionIds") List<Long> permissionIds, @Param("tenantId") Long tenantId);

    /**
     * 统计角色权限关联数量
     * @param tenantId 租户ID
     * @return 关联数量
     */
    @Select("SELECT COUNT(*) FROM sys_role_permission WHERE tenant_id = #{tenantId} AND deleted = 0")
    Long countRolePermissions(@Param("tenantId") Long tenantId);

    /**
     * 统计角色的权限数量
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 权限数量
     */
    @Select("SELECT COUNT(*) FROM sys_role_permission WHERE role_id = #{roleId} AND tenant_id = #{tenantId} AND deleted = 0")
    Long countPermissionsByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Long tenantId);

    /**
     * 统计权限的角色数量
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 角色数量
     */
    @Select("SELECT COUNT(*) FROM sys_role_permission WHERE permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    Long countRolesByPermissionId(@Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 检查角色是否拥有指定权限
     * @param roleId 角色ID
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 是否拥有权限
     */
    @Select("SELECT COUNT(*) > 0 FROM sys_role_permission WHERE role_id = #{roleId} AND permission_id = #{permissionId} AND tenant_id = #{tenantId} AND deleted = 0")
    Boolean checkRoleHasPermission(@Param("roleId") Long roleId, @Param("permissionId") Long permissionId, @Param("tenantId") Long tenantId);

    /**
     * 检查角色是否拥有指定权限代码
     * @param roleId 角色ID
     * @param permissionCode 权限代码
     * @param tenantId 租户ID
     * @return 是否拥有权限
     */
    @Select("SELECT COUNT(*) > 0 FROM sys_role_permission rp " +
            "INNER JOIN sys_permission p ON rp.permission_id = p.id " +
            "WHERE rp.role_id = #{roleId} AND p.permission_code = #{permissionCode} " +
            "AND rp.tenant_id = #{tenantId} AND rp.deleted = 0 AND p.deleted = 0")
    Boolean checkRoleHasPermissionCode(@Param("roleId") Long roleId, @Param("permissionCode") String permissionCode, @Param("tenantId") Long tenantId);
}